﻿using System;
using System.Collections.Generic;

namespace Patterns.Bridge {

    public class AppliedExample {

        public static void Run() {
            // Create RefinedAbstraction
            Customers customers = new Customers("Chicago");

            // Set ConcreteImplementor
            customers.Data = new CustomersData();

            // Exercise the bridge
            customers.Show();
            customers.Next();
            customers.Show();
            customers.Next();
            customers.Show();
            customers.New("Henry Velasquez");

            customers.ShowAll();
        }

        // "Abstraction"
        private class CustomersBase {
            protected string Group { get; set; }
            public DataObject Data { set; get; }

            public CustomersBase(string group) {
                this.Group = group;
            }

            public virtual void Next() {
                Data.NextRecord();
            }

            public virtual void Prior() {
                Data.PriorRecord();
            }

            public virtual void New(string name) {
                Data.NewRecord(name);
            }

            public virtual void Delete(string name) {
                Data.DeleteRecord(name);
            }

            public virtual void Show() {
                Data.ShowRecord();
            }

            public virtual void ShowAll() {
                Console.WriteLine("Customer Group: " + Group);
                Data.ShowAllRecords();
            }
        }

        // "RefinedAbstraction"
        private class Customers : CustomersBase {
            // Constructor
            public Customers(string group)
                : base(group) { }

            public override void ShowAll() {
                // Add separator lines
                Console.WriteLine();
                Console.WriteLine("------------------------");
                base.ShowAll();
                Console.WriteLine("------------------------");
            }
        }

        // "Implementor"
        private abstract class DataObject {
            public abstract void NextRecord();
            public abstract void PriorRecord();
            public abstract void NewRecord(string name);
            public abstract void DeleteRecord(string name);
            public abstract void ShowRecord();
            public abstract void ShowAllRecords();
        }

        // "ConcreteImplementor"
        private class CustomersData : DataObject {
            private List<string> customers = new List<string>();
            private int current = 0;

            public CustomersData() {
                // Loaded from a database
                customers.Add("Jim Jones");
                customers.Add("Samual Jackson");
                customers.Add("Allen Good");
                customers.Add("Ann Stills");
                customers.Add("Lisa Giolani");
            }

            public override void NextRecord() {
                if (current <= customers.Count - 1)
                    current++;
            }

            public override void PriorRecord() {
                if (current > 0)
                    current--;
            }

            public override void NewRecord(string name) {
                customers.Add(name);
            }

            public override void DeleteRecord(string name) {
                customers.Remove(name);
            }

            public override void ShowRecord() {
                Console.WriteLine(customers[current]);
            }

            public override void ShowAllRecords() {
                customers.ForEach(name => 
                    Console.WriteLine(" " + name));
            }
        }
    }
}
